/* 
** (Copyright) sejishikong <sejishikong@263.net>
** Authors:    sejishikong <sejishikong@263.net>
**             Wei Lian <lianwei2003.student@sina.com> 
** Maintainer: Wei Lian
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License Version 2 as
**    published by the Free Software Foundation;
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
*/
#include "header.h"
#include "fork.h"
#include "sys.h"
#include "config.h"
#include "mainwindow.h"
#include "mystatusbar.h"

Fork::Fork (QObject * parent, const char *name):
QObject (parent, name),
mainwindow (static_cast < Sopcast * >(parent))
{

  sop = new QProcess (this);
  connect (sop, SIGNAL (readyReadStdout ()), this, SLOT (parsestdout ()));
  connect (sop, SIGNAL (processExited ()), this, SLOT (onsopexit ()));

  player = new QProcess (this);
  connect (player, SIGNAL (processExited ()), this, SLOT (onplayerexit ()));

  flaghook = FALSE;
  snstatus = 0;
}

Fork::~Fork ()
{
  delete snstatus;
}


////fork new process
bool
Fork::forksop (QString url)
{
  int i;
  char inport[8];
  int sock;
  ///choose inport and outport number
  for (i = 8000; i < 9000; i++)
    {
      sock = Sys::connect_to_server ("127.0.0.1", i);
      if (sock == -1)
	break;
      else if (sock >= 0)
	::close (sock);
    }
  sprintf (inport, "%d", i);
  config->labelinport->setText (inport);

  for (i = 9000; i < 10000; i++)
    {
      sock = Sys::connect_to_server ("127.0.0.1", i);
      if (sock == -1)
	break;
      else if (sock >= 0)
	::close (sock);
    }
  sprintf (outport, "%d", i);
  config->labeloutport->setText (outport);
  ////    
  sop->clearArguments ();
  sop->addArgument ("sp-sc");
  sop->addArgument (url);
  sop->addArgument (inport);
  sop->addArgument (outport);
  return sop->start ();
}

bool
Fork::forkplayer ()
{
  player->clearArguments ();
  QStringList strlst = QStringList::split (" ", config->editplayer->text ());
  for (QStringList::Iterator it = strlst.begin (); it != strlst.end (); ++it)
    {
      player->addArgument (*it);
    }

  QString url = "http://localhost:";
  url += outport;
  player->addArgument (url);
  return player->start ();
}

////kill process
void
Fork::killsop ()
{
  flaghook = FALSE;
  if (sop->isRunning ())
    {
//      sop->tryTerminate ();
      sop->kill ();
    }
}

void
Fork::killplayer ()
{
  if (player->isRunning ())
    {
      player->tryTerminate ();
//      QTimer::singleShot (500, player, SLOT (kill ()));
    }
}

/////////////slots

void
Fork::onplayerexit ()
{
  mainwindow->buttonplayer->setPaletteForegroundColor (Qt::black);
}


void
Fork::onsopexit ()
{
  mainwindow->message[0]->setText ("");
  mainwindow->channelname = "";
}

void
Fork::parsestdout ()
{
  QString str, str1, str2, threadstate;
  str = QString (sop->readStdout ());
  if (str.contains ("detect MTU"))
    {
      mainwindow->message[0]->setText ("Waiting...");
    }

  if (str.contains ("hook_sc"))
    {
      printf ("hook_sc\n");
      if (flaghook == FALSE)
	{
	  //launch statistics monitor
	  int sockfd = Sys::connect_to_server ("127.0.0.1", atoi (outport));
	  if (sockfd < 0)
	    {
	      fprintf (stderr,
		       "failed to create socket, return err %d\n", sockfd);
	      return;
	    }
	  ///set flag
	  flaghook = TRUE;
	  ///bind socket notifier to socket
	  snstatus =
	    new QSocketNotifier (sockfd, QSocketNotifier::Read, this);
	  connect (snstatus, SIGNAL (activated (int)),
		   SLOT (streamready (int)));
	  write (sockfd, "state\ns\n", sizeof ("state\ns\n"));
	  write (sockfd, "state\ns\n", sizeof ("state\ns\n"));
	  ////add widget for statusbar
	  for (int i = 1; i < 6; i++)
	    {
	      mainwindow->statusbar->addWidget (mainwindow->message[i], 1, 0);
	      mainwindow->message[i]->show ();
	    }
	  ////initial value
	  for (int i = 0; i < 6; i++)
	    old_value[i] = -1;
	}
    }
}

void
Fork::streamready (int fd)
{
  char buff[64];
  memset (buff, 0, sizeof (buff));

  int red = 0, size, ret;
  size = sizeof (buff);
  while (1)
    {
      ret =::read (fd, buff + red, size);
      if (ret <= 0)		///server shutdown
	{
	  if (ret < 0)
	    perror ("status socketnotifier");
	  ::close (fd);
	  delete snstatus;
	  snstatus = 0;
	  for (int i = 1; i < 6; i++)
	    {
	      mainwindow->statusbar->removeWidget (mainwindow->message[i]);
	      mainwindow->message[i]->hide ();
	    }

//        mainwindow->message[0]->setText ("");
	  return;
	}
      if (strstr (buff, "\n"))
	break;

      red += ret;
      size -= ret;
    }

  if (buff[0] != 10)
    {
      char *savept;
      strtok_r (buff, "\n", &savept);

      int value[6];
      value[0] = atoi (strtok_r (buff, " ", &savept));
      for (int i = 1; i < 6; i++)
	{
	  value[i] = atoi (strtok_r (NULL, " ", &savept));
	  if (i < 5)
	    value[i] = value[i] / 1024;
	}

      static const char format[][10] =
	{ "%d%%", "ur=%dk", "dr=%dk", "us=%dk", "ds=%dk", "peers=%d" };

      for (int i = 0; i < 6; i++)
	{
	  if (old_value[i] != value[i])
	    {
	      old_value[i] = value[i];
	      sprintf (buff, format[i], value[i]);
	      mainwindow->message[i]->setText (buff);
	    }
	}

    }
  else
    printf ("buff=10\n");

  write (fd, "s\n", sizeof ("s"));
}
